package com.github.alenfive.rocketapi.function;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author negligbleLife
 * @version 1.0
 * @description
 * @createDate 2021/9/26 9:44 上午
 */
public class HttpFunction implements IFunction{

    private  RestTemplate template;
    private  HttpHeaders httpHeaders = new HttpHeaders();
    private  Class<?> responseType = Object.class;
    private  MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
    private  MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
    private  Map<String, ?> variables = new HashMap<>();
    private String url;
    private HttpMethod method = HttpMethod.GET;
    private HttpEntity<Object> entity = null;
    private Object requestBody;



    @Override
    public String getVarName() {
        return "http";
    }

    public HttpFunction(RestTemplate template) {
        this.template = template;
    }

    public HttpFunction(RestTemplate template, String url) {
        this.template = template;
        this.url = url;
    }

    /**
     * 创建连接
     * @param url 目标url
     * @return
     */
    public HttpFunction connect( String url) {
        return new HttpFunction(template, url);
    }

    /**
     * 设置URL参数
     * @param key 参数名
     * @param values 参数值
     * @return
     */
    public HttpFunction param( String key, Object... values) {
        if (values != null) {
            for (Object value : values) {
                this.params.add(key, value);
            }
        }
        return this;
    }

    /**
     * 批量设置URL参数
     * @param values 参数值
     * @return
     */
    public HttpFunction param( Map<String, Object> values) {
        values.forEach((key, value) -> param(key, Objects.toString(value, "")));
        return this;
    }

    /**
     * 设置form参数
     * @param key 参数名
     * @param values 参数值
     * @return
     */
    public HttpFunction data( String key, Object... values) {
        if (values != null) {
            for (Object value : values) {
                this.data.add(key, value);
            }
        }
        return this;
    }

    /**
     * 批量设置form参数
     * @param values 参数值
     * @return
     */
    public HttpFunction data( Map<String, Object> values) {
        values.forEach((key, value) -> data(key, Objects.toString(value, "")));
        return this;
    }

    /**
     * 设置header
     * @param key header名
     * @param value header值
     * @return
     */
    public HttpFunction header( String key,  String value) {
        httpHeaders.add(key, value);
        return this;
    }

    /**
     * 批量设置header
     * @param values header值
     * @return
     */
    public HttpFunction header( Map<String, Object> values) {
        values.entrySet()
                .stream()
                .filter(it -> it.getValue() != null)
                .forEach(entry -> header(entry.getKey(), entry.getValue().toString()));
        return this;
    }

    /**
     * 设置请求方法，默认GET
     * @param method 请求方法
     * @return
     */
    public HttpFunction method( HttpMethod method) {
        this.method = method;
        return this;
    }

    /**
     * 设置`RequestBody`
     * @param requestBody RequestBody
     * @return
     */
    public HttpFunction body( Object requestBody) {
        this.requestBody = requestBody;
        this.contentType(MediaType.APPLICATION_JSON);
        return this;
    }

    /**
     * 自定义`HttpEntity`
     * @param entity HttpEntity
     * @return
     */
    public HttpFunction entity( HttpEntity<Object> entity) {
        this.entity = entity;
        return this;
    }

    /**
     * 设置`ContentType`
     * @param contentType Content-Type值
     * @return
     */
    public HttpFunction contentType( String contentType) {
        return contentType(MediaType.parseMediaType(contentType));
    }

    /**
     * 设置`ContentType`
     * @param mediaType Content-Type值
     * @return
     */
    public HttpFunction contentType( MediaType mediaType) {
        this.httpHeaders.setContentType(mediaType);
        return this;
    }

    /**
     * 发送`POST`请求
     * @return
     */
    public ResponseEntity<Object> post() {
        this.method(HttpMethod.POST);
        return this.execute();
    }

    /**
     * 发送`GET`请求
     * @return
     */
    public ResponseEntity<Object> get() {
        this.method(HttpMethod.GET);
        return this.execute();
    }

    /**
     * 发送`PUT`请求
     * @return
     */
    public ResponseEntity<Object> put() {
        this.method(HttpMethod.PUT);
        return this.execute();
    }

    /**
     * 发送`DELETE`请求
     * @return
     */
    public ResponseEntity<Object> delete() {
        this.method(HttpMethod.DELETE);
        return this.execute();
    }

    /**
     * 执行请求
     * @return
     */
    public ResponseEntity<Object> execute() {
        if (!this.params.isEmpty()) {
            String params = this.params.entrySet().stream()
                    .map(it -> it.getValue().stream()
                            .map(value -> it.getKey() + "=" + value)
                            .collect(Collectors.joining("&"))
                    ).collect(Collectors.joining("&"));
            if (StringUtils.isNotBlank(params)) {
                this.url += (this.url.contains("?") ? "&" : "?") + params;
            }
        }
        if (!this.data.isEmpty()) {
            this.entity = new HttpEntity<>(this.data, this.httpHeaders);
        } else if (this.entity == null && this.requestBody != null) {
            this.entity = new HttpEntity<>(this.requestBody, this.httpHeaders);
        } else {
            this.entity = new HttpEntity<>(null, this.httpHeaders);
        }
        return template.exchange(url, this.method, entity, Object.class, responseType, variables);
    }
}
